﻿using System;
using System.Web;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Caching;
using Stimulus360.Captcha;
using System.Globalization;
using System.ComponentModel;
using Stimulus360.Models.Common;
using System.Collections.Generic;
using Stimulus360.Models.Data.CustomTypes;

namespace Stimulus360.Models.Data
{
    /// <summary>
    ///     This class contains helper extensions for entities .
    /// </summary>
    public static class Extensions
    {
        /// <summary>
        ///     Method to convert a List of InvestmentCategories to its corresponding InvestmentCategorySummary
        /// </summary>
        /// <param name="query">
        ///     List of InvestmentCategories
        /// </param>
        /// <returns>
        ///     List of converted InvestmentCategorySummary
        /// </returns>
        internal static ICollection<InvestmentCategorySummary> InvestmentCategorySummary(this IQueryable<InvestmentCategory> query)
        {
            return
            query.Select(category => new InvestmentCategorySummary
                                         {
                                             Category = category.Category,
                                             CategoryId = category.CategoryId,
                                             Score = category.Score


                                         }).ToList();
        }

        /// <summary>
        ///     Method to get the description of an enum value
        /// </summary>
        /// <param name="enumValue">
        ///     The enum value
        /// </param>
        /// <returns>
        ///     Its description
        /// </returns>
        public static string Description(this Enum enumValue)
        {
            if (enumValue != null)
            {
                DescriptionAttribute[] attributes =
                    (DescriptionAttribute[])
                    enumValue.GetType().GetField(enumValue.ToString()).GetCustomAttributes(
                        typeof (DescriptionAttribute), false);
                return attributes.Length > 0 ? attributes[0].Description : string.Empty;
            }
            return string.Empty;
        }

        /// <summary>
        ///     Helper methog to convert a string into sentence casing with first char uppercase
        /// </summary>
        /// <param name="toBeConverted">
        ///     String to be converted
        /// </param>
        /// <returns>
        ///     String in Sentence Casing.
        /// </returns>
        public static string ToSentenceCasing(this string toBeConverted)
        {
            if (!string.IsNullOrEmpty(toBeConverted))
            {
                string firstChar = toBeConverted.Substring(0, 1);
                string remainingString = toBeConverted.Substring(1, toBeConverted.Length - 1);
                return firstChar.ToUpper(CultureInfo.CurrentCulture) +
                       remainingString.ToLower(CultureInfo.CurrentCulture);
            }
            return string.Empty;
        }

        /// <summary>
        ///     Method to convert a list of UserInterests to its corresponding InvestmentCategorySummary
        /// </summary>
        /// <param name="query">
        ///     The List of User Interests
        /// </param>
        /// <returns>
        ///     The Collection of corresponding InvestmentCategorySummaries
        /// </returns>
        public static ICollection<InvestmentCategorySummary> InterestSummary(this ICollection<UserInterest> query)
        {
            return query.Select(interest => new InvestmentCategorySummary
            {
                Category = interest.Category,
                CategoryId = interest.CategoryId

            }).ToList();
        }

        /// <summary>
        ///     Method to convert a list of Project to their corresponding Project Summaries
        /// </summary>
        /// <param name="query">
        ///     The List of Projects
        /// </param>
        /// <returns>
        ///     The Collection of corresponding Project summaries
        /// </returns>
        public static ICollection<ProjectSummary> ProjectSummary(this IQueryable<Project> query)
        {
            return
            query.Select(project => new ProjectSummary
            {
                ProjectTitle = project.Title,
                ProjectId = project.ProjectId
            }).ToList();
        }

        /// <summary>
        ///     Extension method to generate CSS tag
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of HtmlHelper class</param>
        /// <param name="name">
        ///     Name of CSS file without ".css" extension</param>
        /// <returns>
        ///     Formatted CSS tag.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "helper", Justification ="Parameter needed for helper method")]
        public static string Css(this HtmlHelper helper, string name)
        {
            string path = string.Format(CultureInfo.CurrentCulture, "~/Content/{0}.css", name);
            path = VirtualPathUtility.ToAbsolute(path);
            return string.Format(CultureInfo.CurrentCulture, @"<link href=""{0}"" rel=""stylesheet"" type=""text/css"" />", path);
        }

        /// <summary>
        ///     Extension method to generate CSS tag
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of HtmlHelper class</param>
        /// <param name="name">
        ///     Name of CSS file without ".css" extension
        /// </param>
        /// <param name="media">
        ///     The media string.
        /// </param>
        /// <returns>
        ///     Formatted CSS tag.
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "media"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "helper", Justification = "Parameter needed for helper method")]
        public static string Css(this HtmlHelper helper, string name, string media)
        {
            string path = string.Format(CultureInfo.CurrentCulture, "~/Content/{0}.css", name);
            path = VirtualPathUtility.ToAbsolute(path);
            return string.Format(CultureInfo.CurrentCulture, @"<link href=""{0}"" rel=""stylesheet"" type=""text/css"" media=""screen"" />", path);
        }

        /// <summary>
        ///     Extension method to generate Script tag
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of HtmlHelper class</param>
        /// <param name="name">
        ///     Name of Script file without ".js" extension</param>
        /// <returns>
        ///     Formatted Script tag
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "helper",Justification ="Parameter needed for helper method")]
        public static string Script(this HtmlHelper helper, string name)
        {
            string path = string.Format(CultureInfo.CurrentCulture, "~/Scripts/{0}.js", name);
            path = VirtualPathUtility.ToAbsolute(path);
            return string.Format(CultureInfo.CurrentCulture, @"<script src=""{0}"" type=""text/javascript""></script>", path);
        }

        /// <summary>
        ///     Extension method to generate Script tag with defer attribute
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of HtmlHelper class
        /// </param>
        /// <param name="name">
        ///     Name of Script file without ".js" extension
        /// </param>
        /// <param name="deferText">
        ///     Value of the defer text attribute
        /// </param>
        /// <returns>
        ///     Formatted Script tag
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "helper", Justification = "Parameter needed for helper method")]
        public static string Script(this HtmlHelper helper, string name, string deferText)
        {
            string path = string.Format(CultureInfo.CurrentCulture, "~/Scripts/{0}.js", name);
            path = VirtualPathUtility.ToAbsolute(path);
            return string.Format(CultureInfo.CurrentCulture, @"<script src=""{0}"" type=""text/javascript"" {1}></script>", path, deferText);
        }

        /// <summary>
        ///     Extension method to generate the image tag
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of HtmlHelper class
        /// </param>
        /// <param name="imageName">
        ///     Name of Image file with extenstion
        ///     <example>imageName: NoImage.png</example>
        /// </param>
        /// <param name="imageAltText">
        ///     Value of the alt attribute
        /// </param>
        /// <returns>
        ///     Formatted image tag
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "helper", Justification = "Parameter needed for helper method")]
        public static string Image(this HtmlHelper helper, string imageName, string imageAltText)
        {
            string path = string.Format(CultureInfo.CurrentCulture, "~/Content/images/{0}", imageName);
            path = VirtualPathUtility.ToAbsolute(path);
            return string.Format(CultureInfo.CurrentCulture, "<img src='{0}' alt='{1}' />", path, imageAltText);
        }

        /// <summary>
        ///     Extension method to generate the image tag
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of HtmlHelper class
        /// </param>
        /// <param name="imageName">
        ///     Name of Image file with extenstion
        ///     <example>imageName: NoImage.png</example>
        /// </param>
        /// <param name="imageAltText">
        ///     Value of the alt attribute
        /// </param>
        /// <param name="width">
        ///     Width of the image
        /// </param>
        /// <param name="height">
        ///     Height of the image
        /// </param>
        /// <returns>
        ///     Formatted image tag
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "helper", Justification = "Parameter needed for helper method")]
        public static string Image(this HtmlHelper helper, string imageName, string imageAltText, string width, string height)
        {
            string path = string.Format(CultureInfo.CurrentCulture, "~/Content/images/{0}", imageName);
            path = VirtualPathUtility.ToAbsolute(path);
            return string.Format(CultureInfo.CurrentCulture, "<img src='{0}' alt='{1}' width='{2}' height='{3}' />", path, imageAltText, width, height);
        }

        /// <summary>
        ///     Method to add the list of errors into the Model State
        /// </summary>
        /// <param name="modelState">
        ///     The Model State
        /// </param>
        /// <param name="errors">
        ///     List of errors to be added
        /// </param>
        public static void AddModelError(this ModelStateDictionary modelState, IEnumerable<RuleViolation> errors)
        {
            foreach (var issue in errors)
            {
                modelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
            }
        }

        /// <summary>
        ///     Extension method to generate the rating stars
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of HtmlHelper class
        /// </param>
        /// <param name="ideaId">
        ///     Idea Id
        /// </param>
        /// <param name="value">
        ///     Value of the rating start
        /// </param>
        /// <param name="isChecked">
        ///     Boolean value to set the star is selected or unselected
        /// </param>
        /// <param name="isDisabled">
        ///     Boolean value to disable the star
        /// </param>
        /// <returns>
        ///     Rating control
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "helper", Justification = "Parameter needed for helper method")]
        public static string Rating(this HtmlHelper helper, int ideaId, int value, bool isChecked, bool isDisabled)
        {
            string checkedString = isChecked ? "checked='checked'" : string.Empty;
            string disabledString = isDisabled ? "disabled='disabled'" : string.Empty;

            string ratingCheckbox = "<input name='rating_{0}' type='radio' class='star' title='Rating {1}' value='{1}' {2} {3} />";

            ratingCheckbox = string.Format(CultureInfo.CurrentCulture, ratingCheckbox, ideaId, value, checkedString, disabledString);

            return ratingCheckbox;
        }

        /// <summary>
        ///     Extension method to format the URL
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of UrlHelper class
        /// </param>
        /// <param name="navigateLink">
        ///     Url to navigate
        /// </param>
        /// <param name="query">
        ///     Querystring to attach to an URL
        /// </param>
        /// <returns>
        ///     URL with query string attached
        /// </returns>
        public static string ContentLink(this UrlHelper helper, string navigateLink, string query)
        {
            if (helper != null)
            {
                string strRetVal = helper.Content(navigateLink);
                strRetVal += "/?" + query;
                return strRetVal;
            }
            return string.Empty;
        }

        /// <summary>
        ///     Extention method to generate truncated text by padding '...' at the end of the string
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of HtmlHelper class
        /// </param>
        /// <param name="text">
        ///     Text to be truncated
        /// </param>
        /// <param name="len">
        ///     Required length of the truncated text
        /// </param>
        /// <returns>
        ///     The truncated text
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "helper", Justification = "Parameter needed for helper method")]
        public static string GetTruncatedText(this HtmlHelper helper, string text, int len)
        {
            if (!string.IsNullOrEmpty(text))
            {
                if (text.Length > len)
                    return text.Substring(0, len - 3).Trim() + "...";
                return text.Trim();
            }
            return string.Empty;
        }


        /// <summary>
        ///     This function converts string value to integer
        /// </summary>
        /// <param name="value">
        ///     Value passed for converting to int
        /// </param>
        /// <returns>
        ///     The int value
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int",Justification ="This name is the best representation of the method utility")]
        public static int ToInt(this string value)
        {
            return int.Parse(value,CultureInfo.CurrentCulture );

        }

        /// <summary>
        ///     Extention method to generate CaptchaImage Control
        /// </summary>
        /// <param name="helper">
        ///     A reference to an instance of HtmlHelper class
        ///     </param>
        /// <param name="height">
        ///     Height of the CaptchaImage control
        /// </param>
        /// <param name="width">
        ///     Width of the CaptchaImage control
        /// </param>
        /// <returns>
        ///     CaptchaImage Control
        /// </returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "helper", Justification = "Parameter needed for helper method"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Captcha",Justification ="Captcha is a valid term")]
        public static string CaptchaImage(this HtmlHelper helper, int height, int width)
        {
            CaptchaImage image = new CaptchaImage
            {
                Height = height,
                Width = width,
            };
            Captcha.CaptchaImage.FontWarp = FontWarpFactor.High;
            HttpRuntime.Cache.Add(
                image.UniqueId,
                image,
                null,
                DateTime.Now.AddMinutes(3),
                Cache.NoSlidingExpiration,
                CacheItemPriority.NotRemovable,
                null);

            StringBuilder stringBuilder = new StringBuilder(256);
            stringBuilder.Append("<input type=\"hidden\" name=\"captcha-guid\" value=\"");
            stringBuilder.Append(image.UniqueId);
            stringBuilder.Append("\" />");
            stringBuilder.AppendLine();
            stringBuilder.Append("<img src=\"");
            stringBuilder.Append("/captcha.ashx?guid=" + image.UniqueId);
            stringBuilder.Append("\" alt=\"CAPTCHA\" width=\"");
            stringBuilder.Append(width);
            stringBuilder.Append("\" height=\"");
            stringBuilder.Append(height);
            stringBuilder.Append("\" />");

            return stringBuilder.ToString();
        }
    }

}